package com.fqgj.xjd.user.service.impl;
/**
 * Created by zhangxingyun on 17/7/21.
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.common.utils.MD5;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.exception.enums.BasicErrorCodeEnum;
import com.fqgj.xjd.user.client.UserFrozenService;
import com.fqgj.xjd.user.client.UserService;
import com.fqgj.xjd.user.client.enums.*;
import com.fqgj.xjd.user.client.request.*;
import com.fqgj.xjd.user.client.response.*;
import com.fqgj.xjd.user.common.enums.UserErrorCodeEnum;
import com.fqgj.xjd.user.dao.*;
import com.fqgj.xjd.user.entity.*;
import com.fqgj.xjd.user.entity.business.UserAccessInfoEntity;
import com.fqgj.xjd.user.service.CheckUserService;
import com.fqgj.xjd.user.service.UserAccessService;
import com.fqgj.xjd.user.service.UserRegistService;
import com.fqgj.xjd.user.so.UserAccessToken;
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.qianli.common.enums.AppEnum;
import com.qianli.user.enums.UserAuthStatusEnum;
import com.robert.vesta.util.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @ClassName:
 * @Description: 用户基础服务
 * @Author zhangxingyun
 * @Create 2017-07-21 09:37
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserService.class);

    @Autowired
    UserDao userDao;

    @Autowired
    UserFrozenCodeMapDao userFrozenCodeMapDao;

    @Autowired
    UserAccessDao userAccessDao;

    @Autowired
    CheckUserService checkUserService;

    @Autowired
    UserRegistService userRegistService;

    @Autowired
    UserAccessService userAccessService;

    @Autowired
    UserBehaviorDeviceDao userBehaviorDeviceDao;

    @Autowired
    private UserFrozenService userFrozenService;

    @Autowired
    private UserThirdPartDao userThirdPartDao;

    @Autowired
    private UserCategoryDao userCategoryDao;

    @Autowired
    private UserBehaviorLoginDao userBehaviorLoginDao;
    @Autowired
    private UserQuotaDao userQuotaDao;
    @Autowired
    private UserBaseDao userBaseDao;
    @Autowired
    private UserAuthEmailDao userAuthEmailDao;
    @Autowired
    private UserContactEmergencyDao userContactEmergencyDao;
    @Autowired
    private UserBaseContactDao userBaseContactDao;
    @Autowired
    private UserBaseResidentDao userBaseResidentDao;
    @Autowired
    private UserBaseWorkDao userBaseWorkDao;
    @Autowired
    private UserKycDocumentDao userKycDocumentDao;
    @Autowired
    private UserAuthPanDao userAuthPanDao;
    @Autowired
    private UserOcrInfoDao userOcrInfoDao;
    @Autowired
    private UserAuthBankDao userAuthBankDao;
    @Autowired
    private UserAuthStatusDao userAuthStatusDao;
    @Autowired
    private UserLevelInfoDao userLevelInfoDao;
    @Autowired
    private UserBehaviorRegisterDao userBehaviorRegisterDao;
    @Autowired
    private UserSmsInfoDao userSmsInfoDao;
    @Autowired
    private UserBehaviorDeviceShumeiDao userBehaviorDeviceShumeiDao;
    @Autowired
    private UserContactAddressBookDao userContactAddressBookDao;

    @Autowired
    private UserLiveResDao userLiveResDao;

    @Autowired
    private UserProductPromotionLogDao userProductPromotionLogDao;

    /**
     * 用户注册
     *
     * @param userAccess
     * @param appCode
     * @return
     */
    @Override
    public Response<UserAccessInfo> userRegister(UserAccess userAccess, String appCode) {
        if (userAccess.getMobile() == null) {
            return Response.error(UserErrorCodeEnum.MOBILE_FORMAT_WRONG);
        }

        if (checkUserService.isMobileExist(userAccess.getMobile())) {
            return Response.error(UserErrorCodeEnum.MOBILE_EXIST, UserErrorCodeEnum.MOBILE_EXIST.getMsg());
        }

        UserAccessInfo userAuthAccessInfo = userRegistService.userRegister(userAccess, appCode);
        return Response.ok().putData(userAuthAccessInfo);
    }


    @Override
    public Response<UserAccessInfo> register(UserAccess userAccess, AppCodeEnum appCodeEnum) {
        if (userAccess.getMobile() == null) {
            return Response.error(UserErrorCodeEnum.MOBILE_FORMAT_WRONG);
        }

        if (checkUserService.isMobileExist(userAccess.getMobile(), appCodeEnum)) {
            return Response.error(UserErrorCodeEnum.MOBILE_EXIST, UserErrorCodeEnum.MOBILE_EXIST.getMsg());
        }
        UserAccessInfo userAuthAccessInfo = userRegistService.register(userAccess, appCodeEnum);

        return Response.ok().putData(userAuthAccessInfo);
    }

    @Override
    public Response<UserAccessInfo> thirdPartLogin(ThirdPartLoginTypeEnum loginTypeEnum, Map requestMap, AppEnum appEnum) {
        if (ThirdPartLoginTypeEnum.WE_CHAT.equals(loginTypeEnum)) {
            String openId = (String) requestMap.get("openId");
            if (StringUtils.isNotEmpty(openId)) {
                UserThirdPartEntity userThirdPartEntity = userThirdPartDao.selectOneByOpenId(openId);
                if (userThirdPartEntity == null) {
                    String userCode = IdUtils.genId() + "";
                    userThirdPartEntity = new UserThirdPartEntity()
                            .setUserCode(userCode)
                            .setOpenId(openId)
                            .setOrigin(loginTypeEnum.name());

                    Long sequenceNo = IdUtils.genId();
                    userThirdPartEntity.setId(sequenceNo);
                    userThirdPartDao.insertWithCustomId(userThirdPartEntity);

                    String mockedMobile = sequenceNo.toString();

                    UserAccessEntity userAccessEntity = new UserAccessEntity();
                    UserAccessToken userAccessToken = new UserAccessToken(userCode);
                    userAccessEntity.setUserCode(userCode);
                    userAccessEntity.setAppCode(String.valueOf(appEnum.getAppId()));
                    userAccessEntity.setToken(userAccessToken.getToken());
                    userAccessEntity.setExpireDate(userAccessToken.getExpireDate());
                    userAccessEntity.setMobile(mockedMobile);
                    userAccessEntity.setMd5Mobile(MD5.md5(mockedMobile));
                    userAccessEntity.setCreateDt(new Date());
                    userAccessDao.insert(userAccessEntity);
                    return Response.ok().putData(new UserAccessInfo(userCode, userAccessEntity.getToken(), mockedMobile));
                } else {
                    String userCode = userThirdPartEntity.getUserCode();
                    UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userCode);
                    return Response.ok().putData(new UserAccessInfo(userCode, userAccessEntity.getToken(), userAccessEntity.getMobile()));
                }
            }
        }
        return Response.error(UserErrorCodeEnum.PARAM_ERROR, "Login Failed");
    }

    /**
     * 密码登录
     *
     * @param userAccess
     * @param appCodeEnum
     */
    @Override
    public Response<UserAccessInfo> passwordLogin(UserAccess userAccess, AppCodeEnum appCodeEnum) {
        UserAccessEntity entity = userAccessDao.selectUserByMobileAndAppCode(userAccess.getMobile().getMobile(),
                "" + AppEnum.JYD.getAppId());
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, "Account or password error");
        }
        if (StringUtils.isEmpty(entity.getPassWord())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_SETTED, "Users have not yet set the password.");
        }

        if (!userAccess.getPassword().getPassword().equals(entity.getPassWord())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, UserErrorCodeEnum.PASSWORD_NOT_CORRECT.getMsg());
        }

        if (isFrozen(entity.getUserCode())) {
            return Response.error(UserErrorCodeEnum.FROZEN);
        }

        UserBehaviorDeviceEntity deviceEntity = userBehaviorDeviceDao.selectDeviceByUserCode(entity.getUserCode());
        if (deviceEntity == null
                || userAccess.getUserAppInfo() == null
                || !Objects.equals(deviceEntity.getGuestId(), userAccess.getUserAppInfo().getGuestId())) {
            return Response.error(UserErrorCodeEnum.USER_DEVICE_NOT_BINDED);
        }

        UserAccessToken userAccessToken = userAccessService.refreshUserAccessToken(entity.getUserCode());
        UserAccessInfo userAccessInfo = new UserAccessInfo(entity.getUserCode(), userAccessToken.getToken());
        return Response.ok().putData(userAccessInfo);
    }

    @Override
    public Response<UserAccessInfo> passwordLogin(UserAccess userAccess, String appCode) {
        if (StringUtils.isEmpty(appCode)) {
            return Response.error(UserErrorCodeEnum.APP_CODE_NOT_EMPTY);
        }
        UserAccessEntity entity = userAccessDao.selectUserByMobileAndAppCode(userAccess.getMobile().getMobile(), appCode);
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, "Account or password error");
        }
        if (StringUtils.isEmpty(entity.getPassWord())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_SETTED, "Users have not yet set the password.");
        }

        if (!userAccess.getPassword().getPassword().equals(entity.getPassWord())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, UserErrorCodeEnum.PASSWORD_NOT_CORRECT.getMsg());
        }

        if (isFrozen(entity.getUserCode())) {
            return Response.error(UserErrorCodeEnum.FROZEN);
        }

        /*UserBehaviorDeviceEntity deviceEntity = userBehaviorDeviceDao.selectDeviceByUserCode(entity.getUserCode());
        if (deviceEntity == null
                || userAccess.getUserAppInfo() == null
                || !Objects.equals(deviceEntity.getGuestId(), userAccess.getUserAppInfo().getGuestId())) {
            return Response.error(UserErrorCodeEnum.USER_DEVICE_NOT_BINDED);
        }*/

        UserAccessToken userAccessToken = userAccessService.refreshUserAccessToken(entity.getUserCode());
        UserAccessInfo userAccessInfo = new UserAccessInfo(entity.getUserCode(), userAccessToken.getToken());
        return Response.ok().putData(userAccessInfo);
    }

    /**
     * 验证码登录
     *
     * @param userAccess
     */
    @Override
    public Response<UserAccessInfo> verifyCodeLogin(UserAccess userAccess, String appCode) {
        UserAccessEntity entity = userAccessDao.selectUserByMobile(userAccess.getMobile().getMobile());
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, "Account not exist, please register first.");
        }
        UserAccessToken userAccessToken = userAccessService.refreshUserAccessToken(entity.getUserCode());

        saveUserBehaviorLoginHistory(userAccess, appCode);
        UserAccessInfo userAccessInfo = new UserAccessInfo(entity.getUserCode(), userAccessToken.getToken(), userAccess.getMobile().getMobile(), "");
        return Response.ok().putData(userAccessInfo);
    }

    private void saveUserBehaviorLoginHistory(UserAccess userAccess, String appCode) {
        try {
            UserBehaviorLoginEntity loginEntity = new UserBehaviorLoginEntity();
            loginEntity.setUserCode(userAccess.getUserCode());
            loginEntity.setClientId(userAccess.getUserAppInfo().getClientId());
            loginEntity.setPlatform(userAccess.getUserAppInfo().getPlatform().getType());
            loginEntity.setVersion(userAccess.getUserAppInfo().getVersion());
            loginEntity.setChannel(userAccess.getUserAppInfo().getChannel());
            loginEntity.setChannelId(userAccess.getUserAppInfo().getChannelId());
            loginEntity.setLoginFrom(userAccess.getUserAppInfo().getPlatform().getDesc());
            loginEntity.setGuestId(userAccess.getUserAppInfo().getGuestId());
            loginEntity.setAppCode(appCode);
            loginEntity.setVersionCode(userAccess.getUserAppInfo().getVersionCode());
            loginEntity.setIp(userAccess.getUserAppInfo().getIp());
            loginEntity.setChannelId(userAccess.getUserAppInfo().getChannelId());
            loginEntity.setPackageName(userAccess.getPackageName());
            loginEntity.setAppsflyerId(userAccess.getUserAppInfo().getAppsflyerId());
            List<UserBehaviorLoginEntity> userBehaviorLoginEntities = userBehaviorLoginDao.queryUserLoginList(userAccess.getUserCode(), appCode, userAccess.getPackageName());
            if (CollectionUtils.isEmpty(userBehaviorLoginEntities)) {
                loginEntity.setIsFirstLogin(1);
                LOGGER.info("============= 首次登陆客户 userCode:{}, appCode:{}, packageName:{} ==========", userAccess.getUserCode(), appCode, userAccess.getPackageName());
            }
            userBehaviorLoginDao.insert(loginEntity);
        } catch (Exception e) {
            LOGGER.error("============ saveUserBehaviorLoginHistory:" + e);
        }
    }

    /**
     * 验证码登录 新版
     *
     * @param userAccess
     * @param appEnum
     * @return
     */
    @Override
    public Response<UserAccessInfo> verifyCodeLogin(UserAccess userAccess, AppEnum appEnum) {
        return verifyCodeLogin(userAccess, appEnum, true);
    }

    /**
     * 验证码登录 新版
     *
     * @param userAccess
     * @param appEnum
     * @param needRefreshToken 是否需要刷新Token
     * @return
     */
    @Override
    public Response<UserAccessInfo> verifyCodeLogin(UserAccess userAccess, AppEnum appEnum, Boolean needRefreshToken) {
        Assert.notNull(userAccess);
        Assert.notNull(appEnum);
        Assert.notNull(needRefreshToken);
        //兼容 转换 之前cashmama对应的老app 为JYD
        String appCode;
        if (appEnum.equals(AppEnum.CASH_MAMA)) {
            appCode = AppEnum.JYD.getAppId() + "";
        } else {
            appCode = appEnum.getAppId() + "";
        }
        UserAccessEntity entity = userAccessDao.selectUserByMobileAndAppCode(userAccess.getMobile().getMobile(), appCode);
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_CORRECT, "Account or verification code error");
        }
        if (isFrozen(entity.getUserCode())) {
            return Response.error(UserErrorCodeEnum.FROZEN);
        }
        //刷新Token
        if (needRefreshToken) {
            UserAccessToken userAccessToken = userAccessService.refreshUserAccessToken(entity.getUserCode());
            UserAccessInfo userAccessInfo = new UserAccessInfo(entity.getUserCode(), userAccessToken.getToken());
            return Response.ok().putData(userAccessInfo);
        } else {
            UserAccessInfo userAccessInfo = new UserAccessInfo(entity.getUserCode(), entity.getToken());
            return Response.ok().putData(userAccessInfo);
        }
    }

    /**
     * 设置密码
     *
     * @param userAccess
     */
    @Override
    public Response<Boolean> setPassword(UserAccess userAccess) {

        if (null == userAccess.getPassword()) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_SETTED, "Entry the password please");
        }

        if (StringUtils.isEmpty(userAccess.getUserCode())) {
            return Response.error(UserErrorCodeEnum.PARAM_ERROR, "User ID not set up");
        }

        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userAccess.getUserCode());
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST, "User does not exist");
        }


        if (userAccessService.isUserPasswordSetted(userAccess.getUserCode())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_SETTED, UserErrorCodeEnum.PASSWORD_SETTED.getMsg());
        }

        userAccessService.updateUserPassword(userAccess.getUserCode(), userAccess.getPassword().getPassword());
        return Response.ok().putData(true);
    }

    /**
     * 更新密码
     *
     * @param userAccess
     */
    @Override
    public Response<Boolean> updatePassword(UserAccess userAccess) {
        if (null == userAccess.getPassword()) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_SETTED, "Entry the password please");
        }

        if (StringUtils.isEmpty(userAccess.getUserCode())) {
            return Response.error(UserErrorCodeEnum.PARAM_ERROR, "User ID not set up");
        }

        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userAccess.getUserCode());

        if (null == userAccessEntity || StringUtils.isEmpty(userAccessEntity.getPassWord())) {
            return Response.error(UserErrorCodeEnum.PASSWORD_NOT_SETTED, UserErrorCodeEnum.PASSWORD_NOT_SETTED.getMsg());
        }

        userAccessService.updateUserPassword(userAccess.getUserCode(), userAccess.getPassword().getPassword());
        return Response.ok().putData(true);
    }

    /**
     * 冻结用户
     *
     * @param userCode
     * @param frozeCodeEnum
     */
    @Override
    public Response<Boolean> frozenUser(String userCode, FrozenCodeEnum frozeCodeEnum) {
        frozenUser(userCode, frozeCodeEnum, null);
        return Response.ok().putData(true);
    }

    /**
     * 根据类目冻结用户
     *
     * @param userCode
     * @param frozeCodeEnum
     * @param categoryCode
     * @return
     */
    @Override
    public Response<Boolean> frozenUser(String userCode, FrozenCodeEnum frozeCodeEnum, String categoryCode) {
        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userCode);
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }

        if (null == frozeCodeEnum) {
            return Response.error(UserErrorCodeEnum.FROZEN_NOT_EXIST);
        }
        if (!frozeCodeEnum.equals(FrozenCodeEnum.FROZEN) && !frozeCodeEnum.equals(FrozenCodeEnum.FACE_RECONGNITION)
                && !frozeCodeEnum.equals(FrozenCodeEnum.FIRST_RISK_FROZEN)
                && null == categoryCode) {
            return Response.error(UserErrorCodeEnum.FROZEN_MAP_NEED_CATEGORY_CODE);
        }
        Integer frontDays = 7;
        UserFrozenCodeMapEntity userFrozenCodeMapEntity = userFrozenCodeMapDao.selectUserFrozenCodeMapByUserCodeAndFrozenCode(userCode, frozeCodeEnum.getCode(), categoryCode);
        if (null != userFrozenCodeMapEntity &&
                DateUtil.diffDateToSecond(new Date(), userFrozenCodeMapEntity.getFrozenEndDate()) <= frontDays) {//冻结期
            return Response.error(UserErrorCodeEnum.FROZEN).putData(false);
        }
        userFrozenCodeMapEntity = new UserFrozenCodeMapEntity();
        userFrozenCodeMapEntity.setUserCode(userCode);
        userFrozenCodeMapEntity.setFrozenCode(frozeCodeEnum.getCode());
        userFrozenCodeMapEntity.setCategoryCode(categoryCode);
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, frontDays);
        userFrozenCodeMapEntity.setFrozenEndDate(calendar.getTime());//永久冻结

        userFrozenCodeMapDao.insert(userFrozenCodeMapEntity);
        return Response.ok().putData(true);
    }

    @Override
    public Response<Boolean> borrowFrozenUser(String userCode, String categoryCode, Date gmtDate) {
        UserFrozenCodeMapEntity userFrozenCodeMapEntity = new UserFrozenCodeMapEntity();
        userFrozenCodeMapEntity.setUserCode(userCode);
        userFrozenCodeMapEntity.setFrozenCode(FrozenCodeEnum.BORROW_REJECT.getCode());
        userFrozenCodeMapEntity.setCategoryCode(categoryCode);

        userFrozenCodeMapEntity.setFrozenEndDate(DateUtil.addDate(gmtDate, 90));//永久冻结

        userFrozenCodeMapDao.insert(userFrozenCodeMapEntity);
        return Response.ok().putData(true);
    }

    /**
     * 解冻用户
     *
     * @param userCode
     * @param frozeCodeEnum
     */
    @Override
    public Response<Boolean> unFrozenUser(String userCode, FrozenCodeEnum frozeCodeEnum) {
        unFrozenUser(userCode, frozeCodeEnum, null);
        return Response.ok().putData(true);
    }

    /**
     * 解冻用户
     *
     * @param userCode
     * @param frozeCodeEnum
     */
    @Override
    public Response<Boolean> unFrozenUser(String userCode, FrozenCodeEnum frozeCodeEnum, String categoryCode) {
        UserAccessEntity entity = userAccessDao.selectUserAccessByUserCode(userCode);
        if (null == entity) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }
        if (null == frozeCodeEnum) {
            return Response.error(UserErrorCodeEnum.FROZEN_NOT_EXIST);
        }
//        单一产品无须指定
//        if (!frozeCodeEnum.equals(FrozenCodeEnum.FROZEN) && !frozeCodeEnum.equals(FrozenCodeEnum.FACE_RECONGNITION)
//                && null == categoryCode) {
//            return Response.error(UserErrorCodeEnum.FROZEN_MAP_NEED_CATEGORY_CODE);
//        }

        UserFrozenCodeMapEntity userFrozenCodeMapEntity = userFrozenCodeMapDao.selectUserFrozenCodeMapByUserCodeAndFrozenCode(userCode, frozeCodeEnum.getCode(), categoryCode);
        LOGGER.info("userFrozenCodeMapEntity is {}", userFrozenCodeMapEntity == null ? "no_data" : JSONObject.toJSONString(userFrozenCodeMapEntity));
        if (null == userFrozenCodeMapEntity) {
            return Response.error(UserErrorCodeEnum.FROZEN_MAP_NOT_EXIST);
        }

        userFrozenCodeMapEntity.setDeleted(true);

        userFrozenCodeMapDao.updateByPrimaryKey(userFrozenCodeMapEntity);
        return Response.ok().putData(true);
    }

    /**
     * 获取用户基本信息
     *
     * @param userCode
     * @return
     */
    @Override
    public Response<User> getUserByUserCode(String userCode) {
        UserAccessEntity userEntity = userAccessDao.selectUserAccessByUserCode(userCode);
        User user = buildUser(userEntity);
        return Response.ok().putData(user);
    }

    private User buildUser(UserAccessEntity userEntity) {
        User user = null;
        if (null != userEntity) {
            user = new User();
            BeanUtils.copyProperties(userEntity, user);
            if (org.apache.commons.lang3.StringUtils.isNotBlank(userEntity.getCustomerCode())) {
                UserEntity customer = userDao.selectByCustomerCode(userEntity.getCustomerCode());
                if (customer != null) {
                    user.setName(customer.getName())
                            .setIdentityNo(customer.getIdentityNo());
                }
            }
            List<UserFrozen> frozenList = userFrozenService.getFrozenCode(userEntity.getUserCode());
            if (null != frozenList) {
                user.setFrozenList(frozenList);
            }
        }
        return user;
    }

    private boolean isFrozen(String userCode) {
        List<UserFrozenCodeMapEntity> userFrozenCodeMapEntityList = userFrozenCodeMapDao.selectUserFrozenCodeMapByUserCode(userCode);
        if (userFrozenCodeMapEntityList.size() > 0) {
            for (UserFrozenCodeMapEntity userFrozenCodeMapEntity : userFrozenCodeMapEntityList) {
                if (userFrozenCodeMapEntity.getFrozenCode().equals(FrozenCodeEnum.FROZEN.getCode())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 根据手机号和appCode查询用户
     *
     * @param mobile
     */
    @Override
    public Response<User> getUserByMobile(String mobile, String appCode) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserByMobileAndAppCode(mobile, "" + appCode);
        User user = buildUser(userAccessEntity);
        return Response.ok().putData(user);
    }

    @Override
    public Response<User> getUserByMobile(String mobile) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserByMobile(mobile);
        User user = buildUser(userAccessEntity);
        return Response.ok().putData(user);
    }

    @Override
    public Response<UserAccessInfo> getUserAccessInfoByMobile(String mobile, String appCode) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserByMobileAndAppCode(mobile, "" + appCode);
        if (userAccessEntity == null) {
            return Response.ok().putData(null);
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userCode", userAccessEntity.getUserCode());
        List<UserCategoryEntity> userCategoryEntities = userCategoryDao.selectByParams(paramMap);
        String categoryCode = userCategoryEntities.get(userCategoryEntities.size() - 1).getCategoryCode();
        UserAccessInfo userAccessInfo = new UserAccessInfo();
        BeanUtils.copyProperties(userAccessEntity, userAccessInfo);
        userAccessInfo.setPassword(userAccessEntity.getPassWord());
        userAccessInfo.setProductCategory(categoryCode);//设置用户绑定的产品类目
        return Response.ok().putData(userAccessInfo);
    }

    @Override
    public Response<UserAccessInfo> getUserAccessInfoByMD5Mobile(String md5Mobile, String appCode) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserByMD5MobileAndAppCode(md5Mobile, "" + appCode);
        if (userAccessEntity == null) {
            return Response.ok().putData(null);
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("userCode", userAccessEntity.getUserCode());
        List<UserCategoryEntity> userCategoryEntities = userCategoryDao.selectByParams(paramMap);
        String categoryCode = userCategoryEntities.get(userCategoryEntities.size() - 1).getCategoryCode();
        UserAccessInfo userAccessInfo = new UserAccessInfo();
        BeanUtils.copyProperties(userAccessEntity, userAccessInfo);
        userAccessInfo.setPassword(userAccessEntity.getPassWord());
        userAccessInfo.setProductCategory(categoryCode);//设置用户绑定的产品类目
        return Response.ok().putData(userAccessInfo);
    }

    /**
     * 根据userCode查询UserAccess
     *
     * @param userCode
     * @return
     */
    @Override
    public Response<UserAccessInfo> getUserAccessInfoByUserCode(String userCode) {
        try {
            UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userCode);

            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("userCode", userAccessEntity.getUserCode());
            List<UserCategoryEntity> userCategoryEntities = userCategoryDao.selectByParams(paramMap);

            UserAccessInfo userAccessInfo = new UserAccessInfo();
            BeanUtils.copyProperties(userAccessEntity, userAccessInfo);
            userAccessInfo.setPassword(userAccessEntity.getPassWord());
            userAccessInfo.setProductCategory("all");
            if (!CollectionUtils.isEmpty(userCategoryEntities)) {
                String categoryCode = userCategoryEntities.get(userCategoryEntities.size() - 1).getCategoryCode();
                userAccessInfo.setProductCategory(categoryCode);//设置用户绑定的产品类目
            }

            return Response.ok().putData(userAccessInfo);
        } catch (Exception e) {
            LOGGER.error("getUserAccessInfoByUserCode,查询用户信息失败,userCode:{}", userCode, e);
            return Response.error();
        }
    }

    /**
     * 根据mobile查询UserAccessList
     *
     * @param userAccessQueryRequest
     * @return
     */
    @Override
    public Response<List<UserAccessInfo>> getUserAccessInfoListByMobile(UserAccessQueryRequest userAccessQueryRequest) {
        List<UserAccessInfoEntity> entityList = new ArrayList<>();
        if (StringUtils.isNotEmpty(userAccessQueryRequest.getMobile())) {
            entityList = userAccessDao.selectUserAccessListByMobile(userAccessQueryRequest.getMobile());
        } else if (StringUtils.isNotEmpty(userAccessQueryRequest.getMd5Mobile())) {
            entityList = userAccessDao.selectUserAccessListByMD5Mobile(userAccessQueryRequest.getMd5Mobile());
        } else if (StringUtils.isNotEmpty(userAccessQueryRequest.getMd5MobileIdNo())) {
            entityList = userAccessDao.selectUserAccessListByMD5MobileIdNo(userAccessQueryRequest.getMd5MobileIdNo());
        }
        List<UserAccessInfo> userAccessInfoList = entityList.stream().map(item -> {
            UserAccessInfo userAccessInfo = new UserAccessInfo();
            BeanUtils.copyProperties(item, userAccessInfo);
            return userAccessInfo;
        }).collect(Collectors.toList());
        return Response.ok().putData(userAccessInfoList);
    }

    @Override
    public Response<Customer> getCustomerByMobile(String mobile) {
        LOGGER.info("getCustomerByMobile mobile:" + mobile);
        long startTime = System.nanoTime();
        List<UserEntity> userEntities = userDao.selectByMobile(mobile);
        UserEntity userEntity;
        if (userEntities == null || userEntities.size() == 0) {
            userEntity = null;
        } else {
            userEntity = userEntities.get(0);
        }
        LOGGER.info("getCustomerByMobile mobile : " + mobile + "，cost:" + (System.nanoTime() - startTime) / 1000);
        return Response.ok().putData(usereEntity2Customer(userEntity));
    }

    @Override
    public Response<Customer> getCustomerByMD5Mobile(String md5Mobile) {
        LOGGER.info("getCustomerByMD5Mobile md5Mobile:" + md5Mobile);
        long startTime = System.nanoTime();
        List<UserEntity> userEntities = userDao.selectByMD5Mobile(md5Mobile);
        LOGGER.info("getCustomerByMD5Mobile md5Mobile : " + md5Mobile + "，cost:" + (System.nanoTime() - startTime) / 1000);
        return Response.ok().putData(userEntities2Customer(userEntities));
    }

    @Override
    public Response<Customer> getCustomerByMD5MobileIdNo(String md5MobileIdNo) {
        LOGGER.info("getCustomerByMD5MobileIdNo md5MobileIdNo:" + md5MobileIdNo);
        long startTime = System.nanoTime();
        List<UserEntity> userEntities = userDao.selectByMD5MobileIdNo(md5MobileIdNo);
        LOGGER.info("getCustomerByMD5MobileIdNo md5Mobile : " + md5MobileIdNo + "，cost:" + (System.nanoTime() - startTime) / 1000);
        return Response.ok().putData(userEntities2Customer(userEntities));
    }

    @Override
    public Response<Customer> getCustomerByIdentityNo(String identityNo) {
        return getCustomerByIdentityNoAndCategories(identityNo, null);
    }

    @Override
    public Response<Customer> getCustomerByIdentityNoAndCategories(String identityNo, List<String> categories) {
        List<UserEntity> userEntityList = userDao.selectUserListByIdentityNoAndUserCategories(identityNo, categories);

        Customer customer = null;
        if (CollectionUtils.isNotEmpty(userEntityList)) {
            customer = new Customer();
            customer.setId(userEntityList.get(0).getId());
            customer.setName(userEntityList.get(0).getName());
            customer.setIdentityNo(userEntityList.get(0).getIdentityNo());

            List<String> userCodes = userEntityList.stream().map(UserEntity::getUserCode).collect(Collectors.toList());
            customer.setUserCodes(userCodes);
        }

        return Response.ok().putData(customer);
    }


    @Override
    public Response<List<UserCategory>> getCategoriesListByUserCode(List<String> userCodes) {

        List<UserCategory> userCategories = new ArrayList<>();
        if (CollectionUtils.isEmpty(userCodes)) {
            List<UserCategoryEntity> userCategoryEntities = userCategoryDao.selectListByUserCodes(userCodes);
            if (CollectionUtils.isNotEmpty(userCategoryEntities)) {
                userCategoryEntities.forEach(u -> {
                    UserCategory userCategory = new UserCategory();
                    BeanUtils.copyProperties(u, userCategory);

                    userCategories.add(userCategory);
                });
            }
        }


        return Response.ok().putData(userCategories);
    }

    @Override
    public Response<Customer> getCustomerByMobileAndCategories(String mobile, List<String> categories) {

        LOGGER.info("getCustomerByMobile mobile:" + mobile);
        long startTime = System.nanoTime();
        List<UserEntity> userEntities = userDao.selectByMobileAndCategories(mobile, categories);
        UserEntity userEntity;
        if (userEntities == null || userEntities.size() == 0) {
            userEntity = null;
        } else {
            userEntity = userEntities.get(0);
        }
        LOGGER.info("getCustomerByMobile mobile : " + mobile + "，cost:" + (System.nanoTime() - startTime) / 1000);
        return Response.ok().putData(usereEntity2Customer(userEntity));
    }

    @Override
    public Response<List<User>> getUserListByMobileList(List<String> mobiles, AppCodeEnum appCodeEnum, List<String> categories) {
        List<UserAccessEntity> userAccessEntityList = userAccessDao.selectUserListByMobileListAndAppCode(mobiles, categories);
        List<User> userList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(userAccessEntityList)) {
            for (UserAccessEntity userAccessEntity : userAccessEntityList) {
                User user = buildUser(userAccessEntity);
                userList.add(user);
            }
        }
        return Response.ok().putData(userList);
    }

    /**
     * 更新用户身份
     *
     * @param customerCode
     * @param userTypeEnum
     * @return
     */
    @Override
    public Response<Boolean> updateUserType(String customerCode, UserTypeEnum userTypeEnum) {
        UserEntity userEntity = userDao.selectByCustomerCode(customerCode);
        if (null == userEntity) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }
        userEntity.setUserType(userTypeEnum.getType());
        userDao.updateByPrimaryKey(userEntity);
        return Response.ok().putData(true);
    }


    /**
     * 保存用户头像
     *
     * @param userCode
     * @param avatar
     * @return
     */
    @Override
    public Response<Boolean> updateUserAvatar(String userCode, String avatar, String nickname) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userCode);
        if (null == userAccessEntity) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }
        if (StringUtils.isNotEmpty(avatar)) {
            userAccessEntity.setAvatar(avatar);
        }

        if (StringUtils.isNotEmpty(nickname)) {
            userAccessEntity.setNickname(nickname);
        }
        userAccessDao.updateByPrimaryKey(userAccessEntity);
        return Response.ok().putData(true);
    }

    /**
     * 获取用户登录基本信息
     *
     * @param userCode
     * @return
     */
    @Override
    public Response<UserLoginInfo> getUserLoginInfo(String userCode) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userCode);
        UserLoginInfo userLoginInfo = new UserLoginInfo();
        if (userAccessEntity == null) {
            return Response.error(UserErrorCodeEnum.USER_TOKEN_NOT_EXIST);
        }
        BeanUtils.copyProperties(userAccessEntity, userLoginInfo);
        return Response.ok().putData(userLoginInfo);
    }

    /**
     * 根据token获取
     *
     * @param token
     * @return
     */
    @Override
    public Response<UserLoginInfo> getUserLoginInfoByToken(String token) {
        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByToken(token);
        UserLoginInfo userLoginInfo = new UserLoginInfo();
        if (userAccessEntity == null) {
            return Response.error(UserErrorCodeEnum.USER_TOKEN_NOT_EXIST);
        }
        Date expireDate = userAccessEntity.getExpireDate();
        if (expireDate.before(new Date())) {
            return Response.error(UserErrorCodeEnum.USER_TOKEN_NOT_EXIST);
        }
        BeanUtils.copyProperties(userAccessEntity, userLoginInfo);
        return Response.ok().putData(userLoginInfo);
    }

    @Override
    public Response<UserBehaviorRegister> getRegisterInfo(String userCode) {
        UserBehaviorRegister register = userRegistService.getRegisterInfo(userCode);
        return Response.ok().putData(register);
    }


    @Override
    public Response<List<User>> getUserByUserIdList(List<Long> userIdList) {
        Response<List<User>> response = new Response<>();

        List<UserAccessEntity> userAccessEntityList = userAccessDao.selectListByUserIds(userIdList);
        if (CollectionUtils.isEmpty(userAccessEntityList)) {
            return response.ok();
        }

        List<User> userList = new ArrayList<>();
        for (UserAccessEntity userAccessEntity : userAccessEntityList) {
            userList.add(buildUser(userAccessEntity));
        }

        return response.ok().putData(userList);
    }

    @Override
    public Response<List<User>> getUserByUserCodeList(List<String> userCodeList) {
        Response<List<User>> response = new Response<>();

        List<UserAccessEntity> userAccessEntityList = userAccessDao.selectListByUserCodes(userCodeList);
        if (CollectionUtils.isEmpty(userAccessEntityList)) {
            return response.ok().putData(null);
        }

        List<User> userList = new ArrayList<>();
        for (UserAccessEntity userAccessEntity : userAccessEntityList) {
            userList.add(buildUser(userAccessEntity));
        }

        return response.ok().putData(userList);
    }

    /**
     * @param condition
     * @return
     */
    @Override
    public Response<UserList> queryUserByCondition(UserBaseCondition condition) {
        LOGGER.info("queryUserByCondition conditon:" + JSON.toJSONString(condition));
        Response<UserList> response = new Response<>();
        Integer startIndex = null == condition.getStartIndex() ? 0 : condition.getStartIndex();
        Integer pageSize = null == condition.getPageSize() ? 0 : condition.getPageSize();
        String appCode = null == condition.getAppCode() ? null : condition.getAppCode().getCode();
        String mobile = null == condition.getMobile() ? null : condition.getMobile();
        String idendtityNo = null == condition.getIdentityNo() ? null : condition.getIdentityNo();
        String name = null == condition.getName() ? null : condition.getName();
        Integer total = userAccessDao.countByCondition(AppEnum.JYD.getAppId(), mobile,
                idendtityNo, name);
        condition.setTotalCount(total);
        List<UserAccessEntity> userAccessEntityList = userAccessDao.selectListByCondition(AppEnum.JYD.getAppId(), mobile,
                idendtityNo, name, startIndex, pageSize, condition.getCategoryCode());
        if (CollectionUtils.isEmpty(userAccessEntityList)) {
            return response.ok().putData(null);
        }

        List<User> users = new ArrayList<User>();
        for (UserAccessEntity userAccessEntity : userAccessEntityList) {
            users.add(buildUser(userAccessEntity));
        }
        UserList userList = new UserList();
        userList.setUsers(users);
        userList.setTotalCount(total);
        userList.setTotalPage(condition.getTotalPage());
        //LOGGER.info("queryUserByCondition result:" + JSON.toJSONString(userList));
        return response.ok().putData(userList);
    }

    @Override
    public Response<List<Customer>> searchUserByName(String namePrefix) {
        List<UserEntity> list = userDao.selectByNamePrefix(namePrefix);
        if (CollectionUtils.isEmpty(list)) {
            return Response.ok().putData(Collections.EMPTY_LIST);
        }
        List<String> customerCodes = list.stream().map(UserEntity::getCustomerCode).collect(Collectors.toList());
        List<UserAccessEntity> userList = userAccessDao.selectListByCustomerCode(customerCodes);

        Map<String, List<UserAccessEntity>> map = userList.stream().collect(groupingBy(UserAccessEntity::getCustomerCode));
        List<Customer> rs = new ArrayList<>();
        for (UserEntity customer : list) {
            Customer c = new Customer();
            c.setId(customer.getId());
            c.setName(customer.getName());
            c.setIdentityNo(customer.getIdentityNo());
            List<String> userCodes = null;
            List<UserAccessEntity> users = map.get(customer.getCustomerCode());
            if (CollectionUtils.isNotEmpty(users)) {
                userCodes = users.stream().map(UserAccessEntity::getUserCode).collect(Collectors.toList());
            }
            c.setUserCodes(userCodes);
            rs.add(c);
        }
        return Response.ok().putData(rs);
    }

    private Customer userEntities2Customer(List<UserEntity> userEntities) {
        Customer customer = null;
        if (CollectionUtils.isNotEmpty(userEntities)) {
            customer = new Customer();
            UserEntity userEntity = userEntities.get(0);
            customer.setId(userEntity.getId());
            customer.setName(userEntity.getName());
            customer.setIdentityNo(userEntity.getIdentityNo());
            List<String> userCodes = userEntities.stream().map(UserEntity::getUserCode).collect(Collectors.toList());
            customer.setUserCodes(userCodes);
        }
        return customer;
    }


    private Customer usereEntity2Customer(UserEntity userEntity) {
        Customer customer = null;
        if (null != userEntity) {
            customer = new Customer();
            customer.setId(userEntity.getId());
            customer.setName(userEntity.getName());
            customer.setIdentityNo(userEntity.getIdentityNo());
            List<UserAccessEntity> userEntityList = userAccessDao.selectByCustomerCode(userEntity.getCustomerCode());

            List<String> userCodes = userEntityList.stream().map(UserAccessEntity::getUserCode).collect(Collectors.toList());
            customer.setUserCodes(userCodes);
        }

        return customer;
    }

    /**
     * userCode生成
     *
     * @param mobile
     * @return
     */
    @Override
    public Response<String> produceUserCodeByMobile(String mobile) {
        if (null == mobile || mobile.length() != 11) {
            return Response.error();
        }
        String userCode = IdUtils.genId() + "";
        return Response.ok().putData(userCode);
    }

    @Override
    public Response<String> updateUserMobileByOpenId(ThirdPartLoginTypeEnum loginTypeEnum, String openId, String newMobile) {
        UserThirdPartEntity userThirdPartEntity = userThirdPartDao.selectOneByOpenId(openId);
        if (userThirdPartEntity == null || !userThirdPartEntity.getOrigin().equals(loginTypeEnum.name())) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST, "Login information does not exist"); //三方登陆信息不存在
        }

        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(userThirdPartEntity.getUserCode());
        if (userAccessEntity == null) {
            return Response.error(UserErrorCodeEnum.USER_NOT_EXIST);
        }

        if (userAccessEntity.getMobile().equals(newMobile)) {
            return Response.ok("Update Success");
        }

        userAccessEntity.setMobile(newMobile);
        userAccessDao.updateByPrimaryKey(userAccessEntity);

        return Response.ok().putData(newMobile);
    }

    @Override
    public Response<String> getOpenIdByUserCode(String userCode) {
        UserThirdPartEntity userThirdPartEntity = userThirdPartDao.selectOneByUserCode(userCode);
        if (userThirdPartEntity != null) {
            return Response.ok().putData(userThirdPartEntity.getOpenId());
        }
        return Response.ok();
    }

    @Override
    public Response<Boolean> insertUserAuthentication(UserAuthenticationRequest request) {
        if (request == null || StringUtils.isEmpty(request.getIdNo()) || StringUtils.isEmpty(request.getMobile()) || StringUtils.isEmpty(request.getName())) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "param can be empty");
        }
        UserEntity userEntity = userDao.selectByUserCode(request.getUserCode());
        UserAccessEntity userAccessEntity = userAccessDao.selectUserAccessByUserCode(request.getUserCode());
        if (userEntity == null && userAccessEntity != null) {
            UserEntity newCustomerEntity = new UserEntity();
            newCustomerEntity.setCustomerCode(request.getUserCode());
            newCustomerEntity.setUserCode(request.getUserCode());
            newCustomerEntity.setName(request.getName());
            newCustomerEntity.setIdentityNo(request.getIdNo());
            newCustomerEntity.setMobile(userAccessEntity.getMobile());
            newCustomerEntity.setMd5Mobile(MD5.md5(userAccessEntity.getMobile()));
            newCustomerEntity.setMd5MobileIdentityNo(MD5.md5(userAccessEntity.getMobile() + request.getIdNo()));
            newCustomerEntity.setAppCode(userAccessEntity.getAppCode());
            userDao.insert(newCustomerEntity);
            userAccessDao.updateCustomerCodeByUserCode(request.getUserCode(), request.getUserCode());
        }
        return Response.ok().putData(Boolean.TRUE);
    }

    @Override
    public Response<CopyUserVO> copyUser(CopyUserRequest request) {

        if (request == null || StringUtils.isEmpty(request.getUserCode()) || StringUtils.isEmpty(request.getTargetAppCode())
                || StringUtils.isEmpty(request.getOriginCategoryCode()) || StringUtils.isEmpty(request.getTargetCategoryCode())) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "param can not be empty");
        }

        if (AppCodePackageNameEnum.getEnumByType(request.getTargetAppCode()) == null) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "targetAppCode is not exist");
        }

        UserAccessEntity originUserAccessEntity = userAccessDao.selectUserAccessByUserCode(request.getUserCode());
        if (originUserAccessEntity == null) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "user not exist");
        }

        Map<String, Object> param = new HashMap<>();
        param.put("userCode", originUserAccessEntity.getUserCode());
        param.put("categoryCode", request.getOriginCategoryCode());
        UserQuotaEntity originUserQuota = userQuotaDao.getQutoaByuserCodeAndCategory(param);
        if (originUserQuota == null) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "user quota not exist");
        }

        UserAccessEntity targetUserAccessEntity = userAccessDao.selectUserByMobileAndAppCode(originUserAccessEntity.getMobile(), request.getTargetAppCode());
        UserAccess userAccess = new UserAccess(originUserAccessEntity.getMobile());

        String userCode = null;
        if (targetUserAccessEntity == null) {
            userAppInfoInjection(userAccess, request.getTargetAppCode());

            userCode = IdUtils.genId() + "";

            UserAccessEntity userAccessEntity = new UserAccessEntity();
            UserAccessToken userAccessToken = new UserAccessToken(userAccess.getUserCode());
            userAccessEntity.setUserCode(userAccess.getUserCode());
            if (userAccess.getPassword() != null && StringUtils.isNotEmpty(userAccess.getPassword().getPassword())) {
                userAccessEntity.setPassWord(userAccess.getPassword().getPassword());
            }

            userAccessEntity.setUserCode(userCode);
            userAccessEntity.setAppCode(request.getTargetAppCode());
            userAccessEntity.setToken(userAccessToken.getToken());
            userAccessEntity.setExpireDate(userAccessToken.getExpireDate());
            userAccessEntity.setMobile(userAccess.getMobile().getMobile());
            userAccessEntity.setCreateDt(new Date());
            userAccessEntity.setPackageName(userAccess.getPackageName());
            userAccessEntity.setMd5Mobile(MD5.md5(userAccess.getMobile().getMobile()));
            userAccessDao.insert(userAccessEntity);

            UserBehaviorRegisterEntity userBehaviorRegisterEntity = new UserBehaviorRegisterEntity();
            userBehaviorRegisterEntity.setUserCode(userCode);
            userBehaviorRegisterEntity.setPushType(1);
            userBehaviorRegisterEntity.setClientId(userAccess.getUserAppInfo().getClientId());
            userBehaviorRegisterEntity.setGuestId(userAccess.getUserAppInfo().getGuestId());
            userBehaviorRegisterEntity.setPlatform(userAccess.getUserAppInfo().getPlatform().getType());
            userBehaviorRegisterEntity.setVersion(userAccess.getUserAppInfo().getVersion());
            userBehaviorRegisterEntity.setVersionCode(userAccess.getUserAppInfo().getVersionCode());
            userBehaviorRegisterEntity.setChannel(userAccess.getUserAppInfo().getChannel());
            userBehaviorRegisterEntity.setChannelId(0);
            userBehaviorRegisterEntity.setAppCode(request.getTargetAppCode());
            userBehaviorRegisterEntity.setPackageName(userAccess.getUserAppInfo().getPackageName());
            userBehaviorRegisterEntity.setRegisterFrom("api");
            userBehaviorRegisterEntity.setCreateDate(new Date());

            userBehaviorRegisterDao.insert(userBehaviorRegisterEntity);
            //4. 保存
            UserCategoryEntity userCategoryEntity = new UserCategoryEntity();
            userCategoryEntity.setUserCode(userCode);
            userCategoryEntity.setCategoryCode(request.getTargetCategoryCode());
            userCategoryDao.insert(userCategoryEntity);
            LOGGER.info("用户绑定产品类目 最终 userCode:{},productCategoryName:{}", userCode, request.getTargetCategoryCode());

            //更新状态表
            UserAuthStatusEntity userAuthStatusEntity = new UserAuthStatusEntity();
            userAuthStatusEntity.setUserCode(userCode);
            userAuthStatusDao.insert(userAuthStatusEntity);
            //用户权益
            UserLevelInfoEntity userLevelInfoEntity = new UserLevelInfoEntity()
                    .setLevelCode("0")
                    .setUserCode(userCode)
                    .setCreateDate(new Date())
                    .setScore(0)
                    .setTotalReward(0);
            userLevelInfoDao.insert(userLevelInfoEntity);
        } else {
            userCode = targetUserAccessEntity.getUserCode();
        }

        Map<String, Object> map = new HashMap<>();
        map.put("userCode", userCode);
        map.put("categoryCode", request.getTargetCategoryCode());
        UserQuotaEntity targetUserQuota = userQuotaDao.getQutoaByuserCodeAndCategory(map);
        if (targetUserQuota == null) {
            targetUserQuota = new UserQuotaEntity();
            BeanUtils.copyProperties(originUserQuota, targetUserQuota);
            targetUserQuota.setCategoryCode(request.getTargetCategoryCode());
            targetUserQuota.setUserCode(userCode);
            targetUserQuota.setId(null);
            userQuotaDao.insert(targetUserQuota);
        } else {
            //额度存在则不复制
        }

        UserBaseEntity userBaseEntity = userBaseDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userBaseEntity != null) {
            UserBaseEntity targetUserBaseEntity = userBaseDao.selectByUserCode(userCode);
            if (targetUserBaseEntity == null) {
                targetUserBaseEntity = new UserBaseEntity();
                BeanUtils.copyProperties(userBaseEntity, targetUserBaseEntity);
                targetUserBaseEntity.setUserCode(userCode);
                targetUserBaseEntity.setId(null);
                userBaseDao.insert(targetUserBaseEntity);
            } else {
                UserBaseEntity entity = new UserBaseEntity();
                BeanUtils.copyProperties(userBaseEntity, entity);
                entity.setId(targetUserBaseEntity.getId());
                entity.setUserCode(targetUserBaseEntity.getUserCode());
                userBaseDao.updateByPrimaryKey(entity);
            }
        }

        UserBaseWorkEntity userBaseWorkEntity = userBaseWorkDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userBaseWorkEntity != null) {
            UserBaseWorkEntity targetUserBaseWorkEntity = userBaseWorkDao.selectByUserCode(userCode);
            if (targetUserBaseWorkEntity == null) {
                targetUserBaseWorkEntity = new UserBaseWorkEntity();
                BeanUtils.copyProperties(userBaseWorkEntity, targetUserBaseWorkEntity);
                targetUserBaseWorkEntity.setId(null);
                targetUserBaseWorkEntity.setUserCode(userCode);
                userBaseWorkDao.insert(targetUserBaseWorkEntity);
            } else {
                UserBaseWorkEntity entity = new UserBaseWorkEntity();
                BeanUtils.copyProperties(userBaseWorkEntity, entity);
                entity.setId(targetUserBaseWorkEntity.getId());
                entity.setUserCode(targetUserBaseWorkEntity.getUserCode());
                userBaseWorkDao.updateByPrimaryKey(entity);
            }
        }

        UserContactEmergencyEntity userContactEmergencyEntity = userContactEmergencyDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userContactEmergencyEntity != null) {
            UserContactEmergencyEntity targetUserContactEmergencyEntity = userContactEmergencyDao.selectByUserCode(userCode);
            if (targetUserContactEmergencyEntity == null) {
                targetUserContactEmergencyEntity = new UserContactEmergencyEntity();
                BeanUtils.copyProperties(userContactEmergencyEntity, targetUserContactEmergencyEntity);
                targetUserContactEmergencyEntity.setId(null);
                targetUserContactEmergencyEntity.setUserCode(userCode);
                userContactEmergencyDao.insert(targetUserContactEmergencyEntity);
            } else {
                UserContactEmergencyEntity entity = new UserContactEmergencyEntity();
                BeanUtils.copyProperties(userContactEmergencyEntity, entity);
                entity.setId(targetUserContactEmergencyEntity.getId());
                entity.setUserCode(targetUserContactEmergencyEntity.getUserCode());
                userContactEmergencyDao.updateByPrimaryKey(entity);
            }
        }

        UserBaseResidentEntity userBaseResidentEntity = userBaseResidentDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userBaseResidentEntity != null) {
            UserBaseResidentEntity targetUserBaseResidentEntity = userBaseResidentDao.selectByUserCode(userCode);
            if (targetUserBaseResidentEntity == null) {
                targetUserBaseResidentEntity = new UserBaseResidentEntity();
                BeanUtils.copyProperties(userBaseResidentEntity, targetUserBaseResidentEntity);
                targetUserBaseResidentEntity.setId(null);
                targetUserBaseResidentEntity.setUserCode(userCode);
                userBaseResidentDao.insert(targetUserBaseResidentEntity);
            } else {
                UserBaseResidentEntity entity = new UserBaseResidentEntity();
                BeanUtils.copyProperties(userBaseResidentEntity, entity);
                entity.setId(targetUserBaseResidentEntity.getId());
                entity.setUserCode(targetUserBaseResidentEntity.getUserCode());
                userBaseResidentDao.updateByPrimaryKey(entity);
            }
        }

        UserBaseContactEntity userBaseContactEntity = userBaseContactDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userBaseContactEntity != null) {
            UserBaseContactEntity targetUserBaseContactEntity = userBaseContactDao.selectByUserCode(userCode);
            if (targetUserBaseContactEntity == null) {
                targetUserBaseContactEntity = new UserBaseContactEntity();
                BeanUtils.copyProperties(userBaseContactEntity, targetUserBaseContactEntity);
                targetUserBaseContactEntity.setId(null);
                targetUserBaseContactEntity.setUserCode(userCode);
                userBaseContactDao.insert(targetUserBaseContactEntity);
            } else {
                UserBaseContactEntity entity = new UserBaseContactEntity();
                BeanUtils.copyProperties(userBaseContactEntity, entity);
                entity.setId(targetUserBaseContactEntity.getId());
                entity.setUserCode(targetUserBaseContactEntity.getUserCode());
                userBaseContactDao.updateByPrimaryKey(entity);
            }
        }

        UserKycDocumentEntity userKycDocumentEntity = userKycDocumentDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userKycDocumentEntity != null) {
            UserKycDocumentEntity targetUserKycDocumentEntity = userKycDocumentDao.selectByUserCode(userCode);
            if (targetUserKycDocumentEntity == null) {
                targetUserKycDocumentEntity = new UserKycDocumentEntity();
                BeanUtils.copyProperties(userKycDocumentEntity, targetUserKycDocumentEntity);
                targetUserKycDocumentEntity.setId(null);
                targetUserKycDocumentEntity.setUserCode(userCode);
                userKycDocumentDao.insert(targetUserKycDocumentEntity);
            } else {
                UserKycDocumentEntity entity = new UserKycDocumentEntity();
                BeanUtils.copyProperties(userKycDocumentEntity, entity);
                entity.setId(targetUserKycDocumentEntity.getId());
                entity.setUserCode(targetUserKycDocumentEntity.getUserCode());
                userKycDocumentDao.updateByPrimaryKey(entity);
            }
            //实名认证
            UserEntity userEntityT = userDao.selectByCustomerCode(userCode);
            UserAccessEntity userAccessEntityT = userAccessDao.selectUserAccessByUserCode(userCode);
            UserBaseEntity userBaseEntityT = userBaseDao.selectByUserCode(userCode);
            UserKycDocumentEntity userKycDocumentEntityT = userKycDocumentDao.selectByUserCode(userCode);

            if (userAccessEntityT != null && userBaseEntityT != null && userKycDocumentEntityT != null) {
                UserEntity newCustomerEntity = new UserEntity();
                newCustomerEntity.setAppCode(request.getTargetAppCode());
                newCustomerEntity.setCustomerCode(userCode);
                newCustomerEntity.setUserCode(userCode);
                String name = Joiner.on(" ").skipNulls().join(userBaseEntityT.getFirstName(), userBaseEntityT.getMiddleName(), userBaseEntityT.getLastName());
                newCustomerEntity.setName(CharMatcher.WHITESPACE.trimAndCollapseFrom(name, ' '));
                newCustomerEntity.setIdentityNo(userKycDocumentEntityT.getCardId());
                newCustomerEntity.setMobile(userAccessEntityT.getMobile());
                newCustomerEntity.setMd5Mobile(MD5.md5(userAccessEntityT.getMobile()));
                newCustomerEntity.setMd5MobileIdentityNo(MD5.md5(userAccessEntityT.getMobile() + userKycDocumentEntityT.getCardId()));
                if (userEntityT == null) {
                    userDao.insert(newCustomerEntity);
                    userAccessDao.updateCustomerCodeByUserCode(userCode, userCode);
                } else {
                    newCustomerEntity.setId(userEntityT.getId());
                    userDao.updateByPrimaryKey(newCustomerEntity);
                    userAccessDao.updateCustomerCodeByUserCode(userCode, userCode);
                }
            }
        }

        List<UserOcrInfoEntity> userOcrInfoEntityList = userOcrInfoDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (CollectionUtils.isNotEmpty(userOcrInfoEntityList)) {
            //先删后插
            userOcrInfoDao.deleteByUserCode(userCode);
            for (UserOcrInfoEntity entity : userOcrInfoEntityList) {
                UserOcrInfoEntity targetEntity = new UserOcrInfoEntity();
                BeanUtils.copyProperties(entity, targetEntity);
                targetEntity.setId(null);
                targetEntity.setUserCode(userCode);
                userOcrInfoDao.insert(targetEntity);
            }
        }

        UserAuthPanEntity userAuthPanEntity = userAuthPanDao.selectUserPanByUserCode(originUserAccessEntity.getUserCode());
        if (userAuthPanEntity != null) {
            UserAuthPanEntity targetUserAuthPanEntity = userAuthPanDao.selectUserPanByUserCode(userCode);
            if (targetUserAuthPanEntity == null) {
                targetUserAuthPanEntity = new UserAuthPanEntity();
                BeanUtils.copyProperties(userAuthPanEntity, targetUserAuthPanEntity);
                targetUserAuthPanEntity.setId(null);
                targetUserAuthPanEntity.setUserCode(userCode);
                userAuthPanDao.insert(targetUserAuthPanEntity);
            } else {
                UserAuthPanEntity entity = new UserAuthPanEntity();
                BeanUtils.copyProperties(userAuthPanEntity, entity);
                entity.setId(targetUserAuthPanEntity.getId());
                entity.setUserCode(targetUserAuthPanEntity.getUserCode());
                userAuthPanDao.updateByPrimaryKey(entity);
            }
        }

        UserAuthBankEntity userAuthBankEntity = userAuthBankDao.selectUserBankByUserCode(originUserAccessEntity.getUserCode());
        if (userAuthBankEntity != null) {
            UserAuthBankEntity targetUserAuthBankEntity = userAuthBankDao.selectUserBankByUserCode(userCode);
            if (targetUserAuthBankEntity == null) {
                targetUserAuthBankEntity = new UserAuthBankEntity();
                BeanUtils.copyProperties(userAuthBankEntity, targetUserAuthBankEntity);
                targetUserAuthBankEntity.setId(null);
                targetUserAuthBankEntity.setUserCode(userCode);
                userAuthBankDao.insert(targetUserAuthBankEntity);
            } else {
                UserAuthBankEntity entity = new UserAuthBankEntity();
                BeanUtils.copyProperties(userAuthBankEntity, entity);
                entity.setId(targetUserAuthBankEntity.getId());
                entity.setUserCode(targetUserAuthBankEntity.getUserCode());
                userAuthBankDao.updateByPrimaryKey(entity);
            }
        }

        UserAuthEmailEntity userAuthEmailEntity = userAuthEmailDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userAuthEmailEntity != null) {
            UserAuthEmailEntity targetUserAuthEmailEntity = userAuthEmailDao.selectByUserCode(userCode);
            if (targetUserAuthEmailEntity == null) {
                targetUserAuthEmailEntity = new UserAuthEmailEntity();
                BeanUtils.copyProperties(userAuthEmailEntity, targetUserAuthEmailEntity);
                targetUserAuthEmailEntity.setId(null);
                targetUserAuthEmailEntity.setUserCode(userCode);
                userAuthEmailDao.insert(targetUserAuthEmailEntity);
            } else {
                UserAuthEmailEntity entity = new UserAuthEmailEntity();
                BeanUtils.copyProperties(userAuthEmailEntity, entity);
                entity.setId(targetUserAuthEmailEntity.getId());
                entity.setUserCode(targetUserAuthEmailEntity.getUserCode());
                userAuthEmailDao.updateByPrimaryKey(entity);
            }
        }

        UserSmsInfoEntity userSmsInfoEntity = userSmsInfoDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userSmsInfoEntity != null) {
            UserSmsInfoEntity targetUserSmsInfoEntity = userSmsInfoDao.selectByUserCode(userCode);
            if (targetUserSmsInfoEntity == null) {
                targetUserSmsInfoEntity = new UserSmsInfoEntity();
                BeanUtils.copyProperties(userSmsInfoEntity, targetUserSmsInfoEntity);
                targetUserSmsInfoEntity.setId(null);
                targetUserSmsInfoEntity.setUserCode(userCode);
                userSmsInfoDao.insert(targetUserSmsInfoEntity);
            } else {
                UserSmsInfoEntity entity = new UserSmsInfoEntity();
                BeanUtils.copyProperties(userSmsInfoEntity, entity);
                entity.setId(targetUserSmsInfoEntity.getId());
                entity.setUserCode(targetUserSmsInfoEntity.getUserCode());
                userSmsInfoDao.updateByPrimaryKey(entity);
            }
        }

        UserBehaviorDeviceShumeiEntity userBehaviorDeviceShumeiEntity = userBehaviorDeviceShumeiDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userBehaviorDeviceShumeiEntity != null) {
            UserBehaviorDeviceShumeiEntity targetUserBehaviorDeviceShumeiEntity = userBehaviorDeviceShumeiDao.selectByUserCode(userCode);
            if (targetUserBehaviorDeviceShumeiEntity == null) {
                targetUserBehaviorDeviceShumeiEntity = new UserBehaviorDeviceShumeiEntity();
                BeanUtils.copyProperties(userBehaviorDeviceShumeiEntity, targetUserBehaviorDeviceShumeiEntity);
                targetUserBehaviorDeviceShumeiEntity.setId(null);
                targetUserBehaviorDeviceShumeiEntity.setUserCode(userCode);
                userBehaviorDeviceShumeiDao.insert(targetUserBehaviorDeviceShumeiEntity);
            } else {
                UserBehaviorDeviceShumeiEntity entity = new UserBehaviorDeviceShumeiEntity();
                BeanUtils.copyProperties(userBehaviorDeviceShumeiEntity, entity);
                entity.setId(targetUserBehaviorDeviceShumeiEntity.getId());
                entity.setUserCode(targetUserBehaviorDeviceShumeiEntity.getUserCode());
                userBehaviorDeviceShumeiDao.updateByPrimaryKey(entity);
            }
        }

        UserContactAddressBookEntity userContactAddressBookEntity = userContactAddressBookDao.selectByUserCode(originUserAccessEntity.getUserCode());
        if (userContactAddressBookEntity != null) {
            UserContactAddressBookEntity targetUserContactAddressBookEntity = userContactAddressBookDao.selectByUserCode(userCode);
            if (targetUserContactAddressBookEntity == null) {
                targetUserContactAddressBookEntity = new UserContactAddressBookEntity();
                BeanUtils.copyProperties(userContactAddressBookEntity, targetUserContactAddressBookEntity);
                targetUserContactAddressBookEntity.setId(null);
                targetUserContactAddressBookEntity.setUserCode(userCode);
                userContactAddressBookDao.insert(targetUserContactAddressBookEntity);
            } else {
                //通讯录以设备上传的为准 已经存在则不复制
            }
        }

        UserAuthStatusEntity targetUserAuthStatusEntity = userAuthStatusDao.getUserAuthStatusByUserCode(userCode);
        if (targetUserAuthStatusEntity != null) {
            UserAuthStatusEntity userAuthStatusEntity = userAuthStatusDao.getUserAuthStatusByUserCode(originUserAccessEntity.getUserCode());
            if (userAuthStatusEntity.getAdvanceAadhaarStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setAadhaarStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getAadhaarStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setAadhaarStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getBankStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setBankStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getBaseEmergencyStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setBaseEmergencyStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getBaseInfoStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setBaseInfoStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getBaseWorkStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setBaseWorkStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getDriverLicenseStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setDriverLicenseStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getEmailStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setEmailStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getIsOldUser() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setIsOldUser(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getPassportStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setPassportStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getVoterStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setVoterStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getFirstRoundRiskStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setFirstRoundRiskStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            if (userAuthStatusEntity.getPanStatus() == UserAuthStatusEnum.SUCCESS.getCode()) {
                targetUserAuthStatusEntity.setPanStatus(UserAuthStatusEnum.SUCCESS.getCode());
            }
            userAuthStatusDao.updateByPrimaryKey(targetUserAuthStatusEntity);
        }

        CopyUserVO copyUserVO = new CopyUserVO();
        copyUserVO.setUserCode(userCode);
        copyUserVO.setAppCode(request.getTargetAppCode());
        copyUserVO.setProductCategory(request.getTargetCategoryCode());
        return Response.ok().putData(copyUserVO);
    }

    private void userAppInfoInjection(UserAccess userAccess, String appCode) {
        String guestId = UUID.randomUUID().toString().replace("-", "");
        UserAppInfo userAppInfo = new UserAppInfo(guestId, PlatformEnum.ANDROID, "1.0.0", "cm_api_old_user", guestId, AppCodePackageNameEnum.getEnumByType(appCode).getPackageName());
        userAppInfo.setVersionCode(String.valueOf(1));
        userAccess.setUserAppInfo(userAppInfo);
        userAccess.setPackageName(AppCodePackageNameEnum.getEnumByType(appCode).getPackageName());
    }


    @Override
    public Response<UserLiveRes> getUserLiveRes(String userCode) {
        if (StringUtils.isEmpty(userCode)) {
            return null;
        }

        UserLiveResEntity userLiveResEntity = userLiveResDao.selectOneByUserCode(userCode);
        if (userLiveResEntity == null) {
            return null;
        }

        return Response.ok().putData(new UserLiveRes().setDetail(userLiveResEntity.getDetail())
                .setUserCode(userCode)
                .setScore(userLiveResEntity.getScore()));
    }

    @Override
    public Response<Boolean> addUserLiveRes(UserLiveRes userLiveRes) {
        userLiveResDao.insert(new UserLiveResEntity().setUserCode(userLiveRes.getUserCode())
                .setDetail(userLiveRes.getDetail())
                .setScore(userLiveRes.getScore()));
        return Response.ok().putData(true);
    }

    @Override
    public Response<Boolean> addPromotion(UserProductPromotionLogRes userProductPromotionLogRes) {
        UserProductPromotionLogEntity entity = new UserProductPromotionLogEntity()
                .setActionFrom(userProductPromotionLogRes.getActionFrom())
                .setActionTarget(userProductPromotionLogRes.getActionTarget())
                .setActionType(userProductPromotionLogRes.getActionType())
                .setCreatedDt(new Date());
        userProductPromotionLogDao.insert(entity);
        return Response.ok().putData(true);
    }
}
